package com.bicycle.service.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bicycle.common.entity.base.Message;
import com.bicycle.common.enums.*;
import com.bicycle.common.helper.CoordinateHelper;
import com.bicycle.common.helper.ExcelHelper;
import com.bicycle.common.helper.RedisStringHelper;
import com.bicycle.service.cache.DataCacheOprator;
import com.bicycle.service.dto.BaseJsonMsg;
import com.bicycle.service.entity.BicycleFacilitiesGovArea;
import com.bicycle.service.mapper.BicycleFacilitiesGovAreaMapper;
import com.bicycle.service.service.IBicycleFacilitiesGovAreaService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bicycle.service.vo.BicycleFacilitiesGovAreaGridVo;
import com.bicycle.service.vo.BicycleSystemUserLoginVo;
import com.bicycle.service.vo.KafkaAreaVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.awt.geom.Point2D;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 政府停放区域信息表 服务实现类
 * </p>
 *
 * @author layne
 * @since 2020-08-08
 */
@Service
public class BicycleFacilitiesGovAreaServiceImpl extends ServiceImpl<BicycleFacilitiesGovAreaMapper, BicycleFacilitiesGovArea> implements IBicycleFacilitiesGovAreaService {

    @Autowired
    private RedisStringHelper redisStringHelper;
    @Autowired
    private KafkaTemplate kafkaTemplate;
    @Autowired
    private Environment environment;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Message updateFacilitiesGovAreaByPrimaryKey(BicycleFacilitiesGovArea bicycleFacilitiesGovArea) {
        Message message = new Message();
        // 名称信息是否已存在
        BicycleFacilitiesGovArea qBicycleFacilitiesGovArea = new BicycleFacilitiesGovArea();
//        if (bicycleFacilitiesGovArea.getAreaAttribute() == GovAreaAttributeEnum.AREA_ATTRI_PARK.getKey()) {
        // 停放区
        qBicycleFacilitiesGovArea.setAreaNo(bicycleFacilitiesGovArea.getAreaNo());
//        } else if (bicycleFacilitiesGovArea.getAreaAttribute() == GovAreaAttributeEnum.AREA_ATTRI_MONITOR.getKey()) {
        // 监控区
        qBicycleFacilitiesGovArea.setAreaName(bicycleFacilitiesGovArea.getAreaName());
//        }
        qBicycleFacilitiesGovArea.setHasDel(HasDelEnum.HAS_DEL_FALSE.getKey());
        BicycleFacilitiesGovArea facilitiesGovArea = this.getOne(new QueryWrapper<BicycleFacilitiesGovArea>(qBicycleFacilitiesGovArea));

        // 信息已存在
        if (facilitiesGovArea != null && facilitiesGovArea.getId() != bicycleFacilitiesGovArea.getId().intValue()) {
            message.setCode(FacilitiesBusinessCodeEnum.CODE_INFO_ALREADY_EXISTS.getKey());
            message.setMessage(FacilitiesBusinessCodeEnum.CODE_INFO_ALREADY_EXISTS.getValue());
            return message;
        }
        bicycleFacilitiesGovArea
                .setTaskPoint(bicycleFacilitiesGovArea.getMonitorInterval() == null ? null : bicycleFacilitiesGovArea.getMonitorInterval() % 60);
        bicycleFacilitiesGovArea.setUpdateTime(new Date());
        this.updateById(bicycleFacilitiesGovArea);
        //推送kafka信息
        pushKafkaMessage(bicycleFacilitiesGovArea);
        // 重新加载缓存
        reloadGovAreaCache();
        return message;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Message deleteFacilitiesGovAreaByPrimaryKey(Integer primaryId) {
        Message message = new Message();
        BicycleFacilitiesGovArea bicycleFacilitiesGovArea = new BicycleFacilitiesGovArea();
        bicycleFacilitiesGovArea.setId(primaryId);
        bicycleFacilitiesGovArea.setHasDel(HasDelEnum.HAS_DEL_TRUE.getKey());
        bicycleFacilitiesGovArea.setUpdateTime(new Date());
        this.updateById(bicycleFacilitiesGovArea);

        //推送kafka信息
        pushKafkaMessage(bicycleFacilitiesGovArea);
        // 重新加载缓存
        reloadGovAreaCache();
        return message;
    }

    @Override
    public Message insertFacilitiesGovAreaSelective(BicycleFacilitiesGovArea bicycleFacilitiesGovArea) {
        Message message = new Message();

        // 名称信息是否已存在
        BicycleFacilitiesGovArea qBicycleFacilitiesGovArea = new BicycleFacilitiesGovArea();
//        if (bicycleFacilitiesGovArea.getAreaAttribute() == GovAreaAttributeEnum.AREA_ATTRI_PARK.getKey()) {
        // 停放区
        qBicycleFacilitiesGovArea.setAreaNo(bicycleFacilitiesGovArea.getAreaNo());
//        } else if (bicycleFacilitiesGovArea.getAreaAttribute() == GovAreaAttributeEnum.AREA_ATTRI_MONITOR.getKey()) {
        // 监控区
        qBicycleFacilitiesGovArea.setAreaName(bicycleFacilitiesGovArea.getAreaName());
//        }

        qBicycleFacilitiesGovArea.setHasDel(HasDelEnum.HAS_DEL_FALSE.getKey());
        BicycleFacilitiesGovArea facilitiesGovArea = this.getOne(new QueryWrapper<BicycleFacilitiesGovArea>(qBicycleFacilitiesGovArea));

        // 信息已存在
        if (facilitiesGovArea != null) {
            if (bicycleFacilitiesGovArea.getAreaAttribute() == GovAreaAttributeEnum.AREA_ATTRI_PARK.getKey()) {
                // 停放区
                message.setCode(FacilitiesBusinessCodeEnum.CODE_NUMBER_ALREADY_EXISTS.getKey());
                message.setMessage(FacilitiesBusinessCodeEnum.CODE_NUMBER_ALREADY_EXISTS.getValue());
            } else if (bicycleFacilitiesGovArea.getAreaAttribute() == GovAreaAttributeEnum.AREA_ATTRI_MONITOR.getKey()) {
                // 监控区
                message.setCode(FacilitiesBusinessCodeEnum.CODE_NAME_ALREADY_EXISTS.getKey());
                message.setMessage(FacilitiesBusinessCodeEnum.CODE_NAME_ALREADY_EXISTS.getValue());
            }
            return message;
        }
        // 默认状态设置 未删除 正常状态
        bicycleFacilitiesGovArea.setHasDel(HasDelEnum.HAS_DEL_FALSE.getKey());
        bicycleFacilitiesGovArea.setAreaStatus(GovAreaStatusEnum.AREA_STATUS_NORMAL.getKey());
        bicycleFacilitiesGovArea.setCreateTime(new Date());

        // 计算面积
//        double area = calculateArea(bicycleFacilitiesGovArea.getAreaPoints());
//        bicycleFacilitiesGovArea.setArea((int) area);
        bicycleFacilitiesGovArea
                .setTaskPoint(bicycleFacilitiesGovArea.getMonitorInterval() == null ? null : bicycleFacilitiesGovArea.getMonitorInterval() % 60);
        this.save(bicycleFacilitiesGovArea);

        //推送kafka信息
        pushKafkaMessage(bicycleFacilitiesGovArea);
        // 重新加载缓存
        reloadGovAreaCache();

        return message;
    }

    @Override
    public Integer sumParkValue() {
        return this.getBaseMapper().sumParkValue();
    }

    /**
     * 重新加载企业区域缓存
     *
     * @see
     */
    private void reloadGovAreaCache() {
        DataCacheOprator.getInstance().setRedisStringHelper(redisStringHelper);
        DataCacheOprator.getInstance().reloadGovArea(this.list(new QueryWrapper<BicycleFacilitiesGovArea>(BicycleFacilitiesGovArea.builder().hasDel(HasDelEnum.HAS_DEL_FALSE.getKey()).build())));
    }

    /**
     * 根据上传的经纬度范围获取面积
     *
     * @param areaPoints
     * @return
     * @see
     */
    private double calculateArea(String areaPoints) {
        if (StringUtils.isBlank(areaPoints)) {
            return 0.0;
        }
        JSONArray jsonArray = JSON.parseArray(areaPoints);
        if (jsonArray == null || jsonArray.isEmpty()) {
            return 0.0;
        }
        List<Point2D.Double> points = new ArrayList<Point2D.Double>();

        for (int j = 0; j < jsonArray.size(); j++) {
            double lngd = Double.valueOf(jsonArray.getJSONObject(j).getString("lng"));
            double latd = Double.valueOf(jsonArray.getJSONObject(j).getString("lat"));
            points.add(new Point2D.Double(lngd, latd));
        }
        return CoordinateHelper.getPolygonArea(points);
    }

    /**
     * 推送区域信息
     *
     * @param facilitiesGovArea
     */
    private void pushKafkaMessage(BicycleFacilitiesGovArea facilitiesGovArea) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.setProperty("java.security.auth.login.config", environment.getProperty("java.security.auth.login.config"));
                    KafkaAreaVo kafkaAreaVo = new KafkaAreaVo();
                    BeanUtil.copyProperties(facilitiesGovArea, kafkaAreaVo);
                    if (facilitiesGovArea.getHasDel() == HasDelEnum.HAS_DEL_TRUE.getKey().intValue()) {
                        //已删除区域  推送废除状态
                        kafkaAreaVo.setAreaStatus(3);
                    }
                    String[] topics = environment.getProperty("kafka.topic.ts").split(",");
                    for (int i = 0; i < topics.length; i++) {
                        BaseJsonMsg baseJsonMsg = new BaseJsonMsg();
                        baseJsonMsg.setJsonStr(kafkaAreaVo);
                        if (facilitiesGovArea.getAreaAttribute() == GovAreaAttributeEnum.AREA_ATTRI_ILLEGAL_PARK.getKey().intValue()) {
                            baseJsonMsg.setType(MsgEnums.MSG_FORBID_AREA.getTopicKey());
                            kafkaTemplate.send(topics[i], MsgEnums.MSG_FORBID_AREA.getTopicKey(), JSON.toJSONString(baseJsonMsg));
                        } else if (facilitiesGovArea.getAreaAttribute() == GovAreaAttributeEnum.AREA_ATTRI_PARK.getKey().intValue()) {
                            baseJsonMsg.setType(MsgEnums.MSG_PARK_AREA.getTopicKey());
                            kafkaTemplate.send(topics[i], MsgEnums.MSG_PARK_AREA.getTopicKey(), JSON.toJSONString(baseJsonMsg));
                        } else {
                            log.warn(">>>>>>区域信息不需要推送：" + facilitiesGovArea.toString());
                        }

                    }
                } catch (Exception e) {
                    log.error(">>>>>> 推送区域信息失败，区域：" + facilitiesGovArea.toString());
                    log.error(">>>>>> 推送区域信息失败：", e);
                }
            }
        });
        thread.start();

    }

    /**
     * @Description: 上传导入停放区车辆位置信息
     * @Date: 2021/7/10 0:23
     * @param file:
     * @param userLoginResp:
     * @return: com.bicycle.common.entity.base.Message
     **/
    @Override
    public Message importFacilitiesGovAreaFile(File file, BicycleSystemUserLoginVo userLoginResp) {
        Message message = new Message();
        List<BicycleFacilitiesGovArea> bicycleFacilitiesGovAreaList = new ArrayList<>();
        if(file != null && StringUtils.isNoneBlank(file.getAbsolutePath())) {
            bicycleFacilitiesGovAreaList = readExcelToObject(file,userLoginResp);
            if(bicycleFacilitiesGovAreaList != null && bicycleFacilitiesGovAreaList.size() > 0) {
                for(BicycleFacilitiesGovArea bicycleFacilitiesGovArea : bicycleFacilitiesGovAreaList) {
                    // 名称信息是否已存在
                    BicycleFacilitiesGovArea qBicycleFacilitiesGovArea = new BicycleFacilitiesGovArea();
                    // 停放区
                    qBicycleFacilitiesGovArea.setAreaNo(bicycleFacilitiesGovArea.getAreaNo());
                    // 监控区
                    qBicycleFacilitiesGovArea.setAreaName(bicycleFacilitiesGovArea.getAreaName());

                    qBicycleFacilitiesGovArea.setHasDel(HasDelEnum.HAS_DEL_FALSE.getKey());
                    BicycleFacilitiesGovArea facilitiesGovArea = this.getOne(new QueryWrapper<BicycleFacilitiesGovArea>(qBicycleFacilitiesGovArea));

                    // 信息已存在
                    if (facilitiesGovArea != null) {
                        if (bicycleFacilitiesGovArea.getAreaAttribute() == GovAreaAttributeEnum.AREA_ATTRI_PARK.getKey()) {
                            // 停放区
                            message.setCode(FacilitiesBusinessCodeEnum.CODE_NUMBER_ALREADY_EXISTS.getKey());
                            message.setMessage(FacilitiesBusinessCodeEnum.CODE_NUMBER_ALREADY_EXISTS.getValue());
                        } else if (bicycleFacilitiesGovArea.getAreaAttribute() == GovAreaAttributeEnum.AREA_ATTRI_MONITOR.getKey()) {
                            // 监控区
                            message.setCode(FacilitiesBusinessCodeEnum.CODE_NAME_ALREADY_EXISTS.getKey());
                            message.setMessage(FacilitiesBusinessCodeEnum.CODE_NAME_ALREADY_EXISTS.getValue());
                        }
                        return message;
                    }
                    bicycleFacilitiesGovArea.setCreateTime(new Date());

                    // 计算面积
                    double area = calculateArea(bicycleFacilitiesGovArea.getAreaPoints());
                    bicycleFacilitiesGovArea.setArea((int) area);
                    bicycleFacilitiesGovArea
                            .setTaskPoint(bicycleFacilitiesGovArea.getMonitorInterval() == null ? null : bicycleFacilitiesGovArea.getMonitorInterval() % 60);
                    this.save(bicycleFacilitiesGovArea);

                    //推送kafka信息
                    pushKafkaMessage(bicycleFacilitiesGovArea);
                    // 重新加载缓存
                    reloadGovAreaCache();
                }
            }
        }
        return message;
    }

    /**
     * @Description: 读取Excel表格数据，并组装BicycleFacilitiesGovArea数据
     * @Date: 2021/7/10 11:41
     * @param file:
     * @param userLoginResp:
     * @return: java.util.List<com.bicycle.service.entity.BicycleFacilitiesGovArea>
     **/
    public List<BicycleFacilitiesGovArea> readExcelToObject(File file, BicycleSystemUserLoginVo userLoginResp) {
        BicycleFacilitiesGovArea bicycleFacilitiesGovArea = new BicycleFacilitiesGovArea();
        List<BicycleFacilitiesGovArea> bicycleFacilitiesGovAreaList = new ArrayList<>();
        String cell_val = "";
        try {
            InputStream inputStream = new FileInputStream(file);
            String fileName = file.getName();
            Workbook wb = null;
            if (fileName.endsWith("xls")) {
                wb = new HSSFWorkbook(inputStream);// 解析xls格式
            } else if (fileName.endsWith("xlsx")) {
                wb = new XSSFWorkbook(inputStream);// 解析xlsx格式
            }
            Sheet sheet = wb.getSheetAt(0);    //获得第一个表单
            int rowCount = sheet.getLastRowNum() + 1;
            for (int i = 1; i < rowCount; i++) {
                Row row;
                bicycleFacilitiesGovArea = new BicycleFacilitiesGovArea();
                for (int j = 0; j < sheet.getRow(i).getLastCellNum(); j++) {
                    row = sheet.getRow(i);
                    Cell cell = row.getCell(j);
                    cell_val = cell.toString();
                    if ( j>1 && j<8 && StringUtils.isBlank(cell_val)) {
                        break;
                    }
                    switch (j) {
                        case 0:
                                bicycleFacilitiesGovArea.setAreaName(cell_val);
                            break;
                        case 1:
                            if(StringUtils.isNoneBlank(cell_val)) {
                                bicycleFacilitiesGovArea.setAreaNo(cell_val.substring(0,cell_val.indexOf(".")));
                            }
                            break;
                        case 2:
                            bicycleFacilitiesGovArea.setLat(cell_val);
                            break;
                        case 3:
                            bicycleFacilitiesGovArea.setLng(cell_val);
                            break;
                        case 4:
                            bicycleFacilitiesGovArea.setDistrict(Integer.parseInt(cell_val.substring(0,cell_val.indexOf("."))));
                            break;
                        case 5:
                            bicycleFacilitiesGovArea.setStreet(Integer.parseInt(cell_val.substring(0,cell_val.indexOf("."))));
                            break;
                        case 6:
                            bicycleFacilitiesGovArea.setParkValue(Integer.parseInt(cell_val.substring(0,cell_val.indexOf("."))));
                            break;
                        case 7:
                            bicycleFacilitiesGovArea.setAreaStatus(Integer.parseInt(cell_val.substring(0,cell_val.indexOf("."))));
                            break;
                        case 8:
                            bicycleFacilitiesGovArea.setHasDel(Integer.parseInt(cell_val.substring(0,cell_val.indexOf("."))));
                            break;
                        case 9:
                            bicycleFacilitiesGovArea.setAreaType(Integer.parseInt(cell_val.substring(0,cell_val.indexOf("."))));
                            break;
                        case 10:
                            bicycleFacilitiesGovArea.setAreaAttribute(Integer.parseInt(cell_val.substring(0,cell_val.indexOf("."))));
                            break;
                        case 11:
                            if (cell.getCellTypeEnum() != CellType.STRING && HSSFDateUtil.isCellDateFormatted(cell))
                            {
                                bicycleFacilitiesGovArea.setPeriodBegin(HSSFDateUtil.getJavaDate(cell.getNumericCellValue()));
                            }
                            break;
                        case 12:
                            if (cell.getCellTypeEnum() != CellType.STRING && HSSFDateUtil.isCellDateFormatted(cell))
                            {
                                bicycleFacilitiesGovArea.setPeriodEnd(HSSFDateUtil.getJavaDate(cell.getNumericCellValue()));
                            }
                            break;
                        case 13:
                            bicycleFacilitiesGovArea.setAreaAddress(cell_val);
                            break;
                        case 14:
                            bicycleFacilitiesGovArea.setAreaPoints(cell_val);
                            break;
                        default:
                            break;
                    }
                }
                bicycleFacilitiesGovArea.setCreateBy(userLoginResp.getSysUserId());
                bicycleFacilitiesGovArea.setCreateName(userLoginResp.getUserName());
                bicycleFacilitiesGovArea.setCreateTime(new Date());

                //将GPS经纬度转换为百度地图
                if(StringUtils.isNoneBlank(bicycleFacilitiesGovArea.getLat())
                        && StringUtils.isNoneBlank(bicycleFacilitiesGovArea.getLng())) {
                    double[] lat_lng = CoordinateHelper.wgs2bd(
                            new Double(bicycleFacilitiesGovArea.getLat()),
                            new Double(bicycleFacilitiesGovArea.getLng()));
                    if(lat_lng != null && lat_lng.length == 2) {
                        bicycleFacilitiesGovArea.setLat(lat_lng[0] + "");
                        bicycleFacilitiesGovArea.setLng(lat_lng[1] + "");
                    }
                }

                //将GPS区域经纬度坐标集合批量转换成百度地图坐标
                if(StringUtils.isNoneBlank(bicycleFacilitiesGovArea.getAreaPoints())) {
                    List<BicycleFacilitiesGovArea> govAreaList = new ArrayList<>();
                    BicycleFacilitiesGovArea govArea = new BicycleFacilitiesGovArea();
                    JSONArray jsonArray = JSONArray.parseArray(bicycleFacilitiesGovArea.getAreaPoints());
                    for (Object obj : jsonArray) {
                        govArea = new BicycleFacilitiesGovArea();
                        JSONObject jsonObject = (JSONObject) obj;
                        double[] lat_lng = CoordinateHelper.wgs2bd(
                                new Double(jsonObject.getString("lat")),
                                new Double(jsonObject.getString("lng")));
                        if(lat_lng != null && lat_lng.length == 2) {
                            govArea.setLat(lat_lng[0] + "");
                            govArea.setLng(lat_lng[1] + "");
                            govAreaList.add(govArea);
                        }
                    }
                    if(govAreaList != null && govAreaList.size() > 0) {
                        bicycleFacilitiesGovArea.setAreaPoints(JSON.toJSONString(govAreaList));
                    }
                }
                bicycleFacilitiesGovAreaList.add(bicycleFacilitiesGovArea);
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException("导入失败，文件未找到");
        } catch (IOException e) {
            throw new RuntimeException("导入失败，IO读取异常");
        }
        return bicycleFacilitiesGovAreaList;
    }

    @Override
    public HSSFWorkbook exportFacilitiesGovAreaData(String sheetName,String []title, String [][]values, HSSFWorkbook wb) {
        HSSFWorkbook hssfWorkbook= ExcelHelper.getHSSFWorkbook(sheetName,title,values,wb);
        return hssfWorkbook;
    }

    public static void main(String[] args) {
        /*List<BicycleFacilitiesGovArea> bicycleFacilitiesGovAreaList = new ArrayList<>();
        BicycleFacilitiesGovArea bicycleFacilitiesGovArea = new BicycleFacilitiesGovArea();
        String points = "[{\"lat\":22.583147302,\"lng\":113.949682058},{\"lat\":22.583203625,\"lng\":113.949687599},{\"lat\":22.583202088,\"lng\":113.949707886},{\"lat\":22.583147362,\"lng\":113.94970199}]";
        //2、使用JSONArray
        JSONArray jsonArray=JSONArray.parseArray(points);
        for (Object obj : jsonArray) {
            bicycleFacilitiesGovArea = new BicycleFacilitiesGovArea();
            JSONObject jsonObject = (JSONObject) obj;
            System.out.println(jsonObject.getString("lat")+":"+jsonObject.getString("lng"));
            double[] lat_lng = CoordinateHelper.wgs2bd(
                    new Double(jsonObject.getString("lat")),
                    new Double(jsonObject.getString("lng")));
            if(lat_lng != null && lat_lng.length == 2) {
                bicycleFacilitiesGovArea.setLat(lat_lng[0] + "");
                bicycleFacilitiesGovArea.setLng(lat_lng[1] + "");
                bicycleFacilitiesGovAreaList.add(bicycleFacilitiesGovArea);
                System.out.println("转换后：" + lat_lng[0]+":"+lat_lng[1]);
            }
        }
        System.out.println("List转换为JSON数组：" + JSON.toJSONString(bicycleFacilitiesGovAreaList));*/


    }

}
